PAGE 2

OOP ALLEY


"Programming is understanding." - Kristen Nygaard

CVG5

Here is the Fibonacci program again:


class Fibonacci {
     /** Print out the Fibonacci sequence for values < 50 */
     public static void main (String[] args) {
         int lo = 1;
         int hi = 1;

     System.out.println(lo);
     while (hi < 50) {
          System.out.println(hi);
          hi = lo + hi;       // new hi       
          lo = hi - lo;       /* new lo is (sum-old lo)
                              i.e., the old hi [loops -wb]*/
     }
  }
}

This example declares a Fibonacci class that, like HelloWorld, has a main method.  The 
first two lines of  main declare two variables, hi and lo.  Every variable must have a type
that precedes its name.  hi and lo  are of type int, 32-bit signed [+ or - (wb)] integers with 
values in the range -2 to the 32nd power, through 2 to the 32nd power -1.

Java has built-in "primitive" data types to support integers, floating-point, Boolean, and character 
values.  These primitive types hold data that Java understands directly, as opposed to object types 
defined by programmers.  Java has no "default" types; the type of every variable must be defined 
explicitly.  The primitive data types of Java are:

       boolean                Either true or false 

       char                     16-bit Unicode 1.1 character

       byte                      8-bit integer (signed)

       short                    16-bit integer (signed)

       int                        32-bit integer (signed)

       long                     64-bit integer (signed)

       float                     32-bit floating point (IEEE 754-1985)

       double                  64-bit floating point (IEEE 754-1985)

In the Fibonacci program, we declared hi and lo with initial values of 1.  The starting values 
are set by initialization expressions, using the = operator, when the variables are declared.  The 
= operator sets the variable named on the left-hand side to the value of the expression on the right-
hand side.  In this program, hi is the last term in the series and lo is the previous term.

Variables are undefined prior to initialization.  Should you try to use variables before assigning 
a value, the Java compiler will refuse to compile your program until you fix the problem.

The while statement in the example provides one way of looping in Java. The expression 
inside the while is evaluated -- if true, the body of the loop is executed and the expression 
tested again.  The while is repeated until the expression becomes false.  If it never becomes 
false, the program will run forever, unless something intervenes to break out of the loop, like a
break statement, or an exception handling.

The expression that while tests is a Boolean expression that has the value true or false.
The Boolean expression above tests whether the current high value of the sequence is less than 
50.  If the high value is less than 50, it's value is printed and the next value calculated.  If the 
high value equals or exceeds 50, control passes to the first line of code following the body of the
while loop.  That is the end of the main method in this example, so the program is finished.

Notice that the println method accepts an integer argument in the Fibonacci example 
above, whereas it accepted a string argument in the HelloWorld example.  The  println 
method is one of many methods that are overloaded such that they can accept arguments of 
different types.

Exercises: []Add a title to the printed list.  []Write a program that generates a different sequence,
such as a table of squares (multiplication is done using *, such as i * i).
         
Comments in Code

The English-like things scattered through the code are comments.  Java has three styles of 
comments, all illustrated in the example.

Text following // up to the end of the line is ignored by the compiler, as is text between /* and
the next */ .

Comments enable you to write descriptive text beside your code, to annotate it for future pro-
grammers who may read your code in the future.  The "future programmer" may well be you 
months or years later.  You save yourself effort by commenting your own code.  Also, you 
often find bugs when you write comments: because explaining what the code is supposed to 
do forces you to think about it.

The third kind of comment appears at the very top, between /** and */ .  A comment starting with 
two asterisks is a documentation comment ("doc comment" for short).  Documentation comments 
are intended to desrcibe declarations that follow them.  The comment in the above example is for 
the Main method.  A tool called javadoc extracts documentation comments and generates 
HTML documentation.

Named Constants

Constants are values like 12, 17, 9, and "Strings Like This".  Constants are how 
you specify values that are not computed and recomputed, but remain, well, constant for the life 
of a program.

Programmers prefer named constants for two reasons.  One reason is that the name of the 
constant is a form of documentation.  The name can (and should) describe what the particular 
value is used for.

Another reason is that you define a named constant in a single place in a program.  When the 
constant needs to be changed or corrected, it can be changed in only one place, easing program 
maintenance.  Named constants in Java are created by declaring a variable as static and 
final, and providing its initial value in the declaration:   

class CircleStuff {
        static final double p = 3.1416;
}


The value of p can be changed in just one place when we discover that five significant digits of 
precision are not enough.  We declared p as double -- a double-precision 64-bit floating-
point number.  Now we could change p to a more precise value, like 3.14159265358979323846.

You can group related constants within a class.  For example, a card game might use these 
constants: 


class Suit {
       final static int CLUBS     = 1;
       final static int DIAMONDS  = 2;
       final static int HEARTS    = 3;
       final static int SPADES    = 4;
};
 

With this declaration, Suit in a program would be accessed as Suit.HEARTS, 
Suit.SPADES, and so on, thus grouping all the suit names within the single name Suit.

Unicode Characters

We take a minor diversion to note the psymbol as the name of a constant in the previous 
example.  In most programming languages, identifiers are usually limited to the letters and digits 
available in the ASCII character set.

Java moves you toward the modern world of internationalized software: You write Java code in
Unicode -- an international character-set standard.  Unicode characters are 16 bits and provide 
a character range large enough to write the major languages used in the world, which is why we 
can use p for the name of the value in the example above.  p is a valid letter from the Greek 
section of Unicode, and therefore valid in Java source.  Most existing Java code is written 
in ASCII, a 7-bit character standard, or ISO-Latin-1, an 8-bit character standard commonly 
called "Latin-1."  But they are translated into Unicode before processing so the Java char-
acter set is always Unicode.  

Exercises:  []Change the HelloWorld application to use a named string constant as the string 
to print.  []Change the Fibonacci application to use a named constant in its loop instead of a 
literal constant.

Flow of Control

"Flow of control" is the term for deciding which statements in a program are executed.  The
While loop in the Fibonacci program is one way.  Other flow-of-control statements include
if/else, for, switch, do/while, and blocks -- multiple statements grouped within 
{ and } .  We change the Fibonacci sequence program by numbering the elements of the sequence, 
and marking even numbers with an asterisk:


class ImprovedFibonacci {
     /** Print out the first few Fibonacci 
       * numbers, marking evens with a '*' */
     static final int MAX_INDEX = 10;     

     public static void main (String[] args) {
         int lo = 1;
         int hi = 1;
         String mark;

         System.out.println("1: " + lo);
         for (int I = 2; I < MAX_INDEX; I++) {
              if (hi % 2 == 0)
                  mark = " *";
              else
                  mark = "";
              System.out.println(i + ": " + hi + mark);
              hi = lo + hi;       // new hi       
              /* new lo is (sum-old lo) i.e., the old hi */
              lo = hi - lo;   
         }
     }
}


Here is the new output:


  1: 1
  2: 1
  3: 2 *
  4: 3
  5: 5
  6: 8 *
  7: 13
  8: 21
  9: 34 *   

   

To number the elements of the sequence, we used a for loop instead of a while loop.  A
for loop is shorthand for a while loop, but with an initialization and increment phase added.
The for loop above is equivalent to this while loop:     


  {
       int I = 2;
       while (I < MAX_INDEX) {
             // .. do the printing stuff
             I++;
       }
   } 

   

The ++ operator in the code fragment above may be unfamiliar if you're new to C-derived
programming languages.  The plus-plus operator increments by one the value of any variable
it abuts -- the contents of variable i in this case.  The ++ operator is a prefix operator when it 
comes before its operand, and postfix when it comes after.  Similarly, minus-minus decrements 
by one the value of any variable it abuts, and can also be prefix or postfix.  The ++ and -- opera-
tors come from the C programming language.  In the context of the example above, a statement like

      i++;

is equivalent to

      i = i + 1; 

Beyond simple assignment, Java supports other assignment operators that apply an arithmetic 
operation to the value on the left-hand side of the operator.  For example, another way to 
write i++ in the for loop above would be to write

      i += 1;

which adds the value on the right-hand side of the += operator (namely 1) to the variable 
on the left-hand side (namely i).  Many of the binary operators in Java (operators that take
two operands) can be joined with the = in a similar way.

Inside the for loop we use an if/else to see if the current hi value is even.  The if
statement tests the expression between the parentheses.  If the expression is true, the first
statement or block in the body of the if is executed.  If the expression is false, the statement
or block following the else clause is executed.  The else part is optional: if the  else is
not present, nothing is done when the expression is false.  After figuring out which (if any) clause 
to execute, control passes to the code following the body of the if statement.

The example tests if hi is even, using the % or remainder [sometimes called modulus-WedB]
operator.  It produces the remainder after dividing the value on the left side by the value on the 
right. [In our example at hand -WedB]If the left-side value is even, the remainder 0, and the fol-
lowing statement assigns a string containing the even-numbered indicator to marker.  The
else clause is executed for odd numbers, setting marker to an empty string. [Hence the 
empty "" -WedB]             

The println invocation is more complex, using the + operator to concatenate [Stick things
together just as they present themselves per the concatenation coding requirements. -WedB] 
strings representing i, a separator, a string representing hi, and the marker string.  The + 
operator is a concatenation operator when used with strings, whereas it is an addition operator
when used in arithmetic expressions.

Exercise: []Change the loop so that i counts backward instead of forward.

Classes and Objects

Java, like any object-oriented programming language, provides a tool to solve programming
problems using the notions of classes and objects.  Objects in Java have a type; that type is 
the object's class.  Each class type has two kinds of members, namely fields and methods.

     * Fields are data variables associated with a class and its objects.  Fields 
       store results of computations performed by the class's methods.

     * Methods contain the executable code of a class.  Methods are built from 
       statements.  The way in which methods are invoked and the statements 
       contained within those methods are what ultimately directs program execution.

Here is the declaration of a simple class that might represent a point on a two-dimensional plane:

class Point {
     public double x, y;
} 

This Point class has two fields representing the x and y coordinates of a point, and 
has (as yet) no methods.  A class declaration like this one is, conceptually, a plan that 
defines what objects manufactured from that class look like, plus sets of instructions
that define the behavior of those objects.  The blueprint of an object adds its maximum 
value when you use the plans and instructions in the blueprint to manufacture goods
(objects) from those plans.

Members of a class can have various levels of visibility.  The public declaration of x 
and y in the Point class means that any code with access to a Point object can read 
or modify those values.  Other levels of visibility limit member access to code in the 
class itself, or to other related classes.

Creating Ojects

Objects are created using an expression containing the new keyword.  Creating an object 
from a class definition is also known as instantiation; thus objects are often called 
instances.

In Java, newly created objects are allocated within an area of syste memory known as the
heap.  All objects in Java are created vis object references -- any variable that appears 
to hold an object actually contains a reference to that object.  Object referenes are null
 when they do not reference any object.

Most of the time you can be imprecise in the distinction between actual objects and refer-
ences to objects.  You can say "pass the object to the method" when you really mean "pass
an object reference to the method."  We are careful about this distinction only where it
makes a difference.  Most of the time, you can use "object" and "object reference" inter-
changeably.

Getting back to the Point class defined previously, suppose you are building a graphics
application in which you need to track lots of points.  You represent each point by its own 
concrete Point object.  Here is how you might create and initialize Point objects.

Point  lowerLeft = new Point ();
Point  upperRight = new Point ();
Point  middlePoint = new Point ();

lowerLeft.x = 0.0;
upperLeft.y = 0.0;

upperRight.x = 1280.0;
upperRight.y = 1024.0;

middlePoint.x = 640.0;
middlePoint.y = 512.0;
 

Each Point object is unique and has its own copy of the x and y fields.  Changing 
x in the lowerLeft, for example, does not affect the value of x in upperRight object.  
The fields in objects are known as instance variables, because there is a unique copy of the 
in each object (instance) of the class.

Static or Class Fields

Per-object fields are usually what you need.  You usually want a field in one object to be 
distinct from the similarly named field in every other object instantiated from that class.

Sometimes, though, you want fields that are shared among all objects of that class.  These
shared variables are known as class variables -- variables specific to the class as opposed 
[being specific -WedB] to objects of the class.

Why would you want to use class variables?  Consider the Sony Walkman factory.  Each 
Walkman has a unique serial number.  In object terms, each Walkman object has its own 
unique serial number field.  However, the factory needs to keep a record of the next serial 
number to be assigned.  You don't want to keep that number with every Walkman object -- 
you'd keep only one copy of that number in the factory, or in object terms, as a class 
variable.  

In Java, you obtain class-specific fields by declaring them static, and they are therefore 
sometimes called static fields.  For example, a Point object to represent the origin might
be common enough that you should provide it as a static field in the Point class:


   public static Point origin = new Point ();

If this declaration appears inside the declaration of the Pointclass, there will be exactly
one piece of data called Point.origin that always refers to an object at (0,0).  This
 static field is there no matter how many Point objects are created, even if none
is created.  The values of x and y are zero because that is the default for numeric fields
that are not explicitly initialized to a different value.

You saw one static object in your first program.  The System class is a standard Java
class that has a static field named out for printing output to the standard output stream.

When you see "field" in this in this chapter, it generally means a per-object field, although 
the term "non-static field" is sometimes used for clarity.

The Garbage Collector

After creating an object using new, how do you get rid of the object when you no longer
want it?  The answer is simple: You don't.  Unused Java objects are automatically reclaimed 
by a garbage collector.  The garbage collector runs in the background and tracks object 
references.  When an object no longer has any reference, it can be removed from the storage 
allocation heap, although its actual removal may be delayed until a propitious time.

Methods and Parameters

Objects of the Point class as defined above are exposed to manipulation by any code that 
has a reference to a Point object, because its fields are declared public.  The  Point 
class is an example of the very simplest kind of class.  Indeed, some classes are this simple, 
when they are designed to fit purely internal needs for a package, or when simple data 
containers are all you need.

The real benefits of object orientation, however, come from hiding the implementation of a 
class behind operations performed on its internal data.  In Java, operations of a class are 
declared via its methods -- instructions that operate on an objects data to obtain results.  
Methods access internal implementation details that are otherwise hidden from other objects.  
Hiding data behind methods so that it is inaccessible to other objects is the fundamental 
basis of data encapsulation.

Methods have zero or more parameters.  A method can return a value, or it can be declared
 void to indicate that it does not return any value.  A method's statements appear in a 
block of code between curly braces { and } that follow the method's name and the declar-
ation of its signature.  The signature is the name of the method and the number and types 
of the method's parameters.  If we enhance the Point class with a simple clear method, 
it might look like this:


   public void clear() {
         x=0;
         y=0;
   }  


The clear method has no parameters, hence the empty ( and ) after its name; in addition, 
clear is declared void because it does not return any value.  Inside a method, fields 
and other methods of the class can be named directly -- we can simply say x and y without 
an explicit object reference.

Invoking a Method       

Objects in general do not operate directly on the data of other objects although, as you saw
in the Point class, a class can make its fields publicly accssible.  In general though, 
well-designed classes hide their data so that it can be changed only by methods of that class.
To invoke a method, you provide an object reference and the method name, sparated by a dot (.).
Parameters are passed to the method as a comma-separated list of values enclosed in parentheses.
Methods that take no parameters still require the parentheses, with nothing between them. The
object on which the method is invoked (the object receiving the method invocation) is often 
known as the receiving object [or] the receiver.

A method may return a single value as a result.  To return more than one value from a method, 
create an object whose sole purpose is to hold return values in a single unit, and then return
that object.

Here is a method called distance that's part of the Point class shown in previous
examples.  The distance method accepts another Point object as a parameter, com-
putes the Euclidean distance between itself and the other point, and returns a double-precision
floating-point result:


  public double distance(Point that) {
       double xdiff, ydiff;
       xdiff = x - that.x;
       ydiff = y - that.y;
       return Math.sqrt(xdiff ( xdiff + ydiff * ydiff);
  } 

  
| NEXT PAGE | PREVIOUS PAGE | PHIL-LIT | LOADING DOC |

Email me at memphis@consultant.com

[yes?]

Moyra's Web Jewels

This page created by BITS

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>